#include "RingQueue.hpp"
#include "Task.hpp"
#include <iostream>
#include <pthread.h>
#include <ctime>
#include <sys/types.h>
#include <unistd.h>



void* ProductorRoutine(void* args)
{
    // RingQueue<int>* rq = static_cast<RingQueue<int>*>(args);

    RingQueue<Task>* rq = static_cast<RingQueue<Task>*>(args);

    while(true)
    {
        // version 1
        // int data = rand() % 10;
        // rq->push(data);
        // std::cout << "productor thread " << "生产了数据：" << data << std::endl; 
        
        // sleep(2);
        // version 2
        int x = rand() % 10;
        int y = rand() % 5;
        char op = operations[rand() % operations.size()];
        Task t(x, y, op, MyMath);
        rq->push(t);
        std::cout << "productor thread: " << pthread_self() << " "<< t.toTastString() << std::endl;
    }
}


void* ConsumerRoutine(void* args)
{
    // RingQueue<int>* rq = static_cast<RingQueue<int>*>(args);

    RingQueue<Task>* rq = static_cast<RingQueue<Task>*>(args);
    while(true)
    {
        // version 1
        // int data;
        // rq->pop(&data);
        // std::cout << "consumer thread" << "消费了数据：" << data << std::endl;


        // version 2
        Task t;
        rq->pop(&t);
        std::cout << "consumer thread " << pthread_self() << " "<< t() << std::endl;

    }
}


int main()
{
    srand((unsigned int)time(nullptr));
    // RingQueue<int>* rq = new RingQueue<int>(); 
    RingQueue<Task>* rq = new RingQueue<Task>(); 

    // pthread_t p, s;
    // pthread_create(&p, nullptr, ProductorRoutine, rq);
    // pthread_create(&s, nullptr, ConsumerRoutine, rq);

    // pthread_join(p ,nullptr);
    // pthread_join(s ,nullptr);


    pthread_t p[4], c[6];

    for(int i = 0; i < 4; ++i)
    {
        pthread_create(p + i, nullptr, ProductorRoutine, rq);
    }
    for(int i = 0; i < 6; ++i)
    {
        pthread_create(c + i, nullptr, ConsumerRoutine, rq);
    }

    for(auto& e : p)
    {
        pthread_join(e, nullptr);
    }

    for(auto& e : c)
    {
        pthread_join(e, nullptr);
    }


    return 0;
}